package filesync;

import java.io.File;
import java.io.IOException;

import net.contentobjects.jnotify.JNotify;
import net.contentobjects.jnotify.JNotifyException;
import net.contentobjects.jnotify.JNotifyListener;

public class Monitor {
    private MonitorSpec spec;
    private int watchId;
    private String srcAbsolute;
 
    public File getSource() { return spec.getSource(); }
    public File getTarget() { return spec.getTarget(); }
    public String[] getPatterns() { return spec.getPatterns(); }

    public Monitor(MonitorSpec spec) throws JNotifyException, InterruptedException {
        this.spec = spec;
        srcAbsolute = spec.getSource().getAbsolutePath();
        startMonitoring();
    }
    
    private File getDestinationFile(File src) {
        String delta = src.getAbsolutePath().substring(srcAbsolute.length());
        //System.out.println("Delta:" + delta);
        //System.out.println("Dest:" + new File(spec.getTarget().getAbsoluteFile(), delta));
        return new File(spec.getTarget().getAbsoluteFile(), delta);
    }

    private void startMonitoring() throws JNotifyException, InterruptedException {
        int mask =  JNotify.FILE_CREATED | JNotify.FILE_DELETED | JNotify.FILE_MODIFIED | JNotify.FILE_RENAMED;
        boolean watchSubtree = true;
        watchId = JNotify.addWatch(spec.getSource().getAbsolutePath(), mask, watchSubtree, new JNotifyListener() {
            public void fileRenamed(int wd, String rootPath, String oldName, String newName) {
                if (FileUtil.matches(new File(rootPath, newName).getPath(), spec.getPatterns())) {
                    System.out.println("Monitor " + wd + " renamed: " + rootPath + ", " + oldName + " -> " + newName);
                    File newFile = new File(rootPath, newName);
                    try {
                        FileCopy.copyFile(newFile, getDestinationFile(newFile));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            public void fileModified(int wd, String rootPath, String name) {
                if (FileUtil.matches(new File(rootPath, name).getPath(), spec.getPatterns())) {
                    System.out.println("Monitor " + wd + " modified: " + rootPath + ", " + name);
                    File newFile = new File(rootPath, name);
                    try {
                        FileCopy.copyFile(newFile, getDestinationFile(newFile));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            public void fileDeleted(int wd, String rootPath, String name) {
                if (FileUtil.matches(new File(rootPath, name).getPath(), spec.getPatterns())) {
                    System.out.println("Monitor " + wd + " deleted: " + rootPath + ", " + name);
                }
            }

            public void fileCreated(int wd, String rootPath, String name) {
                if (FileUtil.matches(new File(rootPath, name).getPath(), spec.getPatterns())) {
                    System.out.println("Monitor " + wd + " created: " + rootPath + ", " + name);
                    File newFile = new File(rootPath, name);
                    try {
                        FileCopy.copyFile(newFile, getDestinationFile(newFile));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    public void stopMonitoring() throws JNotifyException {
        boolean res = JNotify.removeWatch(watchId);
        if (!res) {
            System.out.println("invalid watch ID specified: " + watchId);
        }
    }
}
